﻿using System;
using System.Threading.Tasks;

using Windows.UI.Xaml;

using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;

using Uhimania.Libraries.Test;

using Uhimania.Libraries.Windows.Interactivity;

namespace Windows.InteractivityTest
{
    [TestClass]
    public class BehaviorCollectionTest
    {
        #region AssociatedObject

        #region 正常ケース
        [TestMethod]
        public async Task AssociatedObject_正常ケース()
        {
            await UiTestHelper.ExecuteOnUiThread(() =>
            {
                var associated = new Mock();

                var item1 = new BehaviorMock();
                var item2 = new BehaviorMock();

                var collection = new BehaviorCollection();
                collection.Add(item1);
                collection.Add(item2);
                item1.AssociatedObject.IsNull();
                item2.AssociatedObject.IsNull();

                collection.Attach(associated);
                collection.AssociatedObject.Is(associated);
                item1.AssociatedObject.Is(associated);
                item2.AssociatedObject.Is(associated);

                collection.Detach();
                collection.AssociatedObject.IsNull();
                item1.AssociatedObject.IsNull();
                item2.AssociatedObject.IsNull();
            });
        }
        #endregion

        #endregion

        #region CollectionChanged

        #region Add
        [TestMethod]
        public async Task CollectionChanged_Add()
        {
            await UiTestHelper.ExecuteOnUiThread(() =>
            {
                var associated = new Mock();
                var collection = new BehaviorCollection();
                collection.AssociatedObject = associated;

                var item1 = new BehaviorMock();
                var item2 = new BehaviorMock();

                collection.Add(item1);
                item1.AssociatedObject.Is(associated);
                item2.AssociatedObject.IsNull();

                collection.Insert(0, item2);
                item1.AssociatedObject.Is(associated);
                item2.AssociatedObject.Is(associated);
            });
        }
        #endregion

        #region Remove
        [TestMethod]
        public async Task CollectionChanged_Remove()
        {
            await UiTestHelper.ExecuteOnUiThread(() =>
            {
                var associated = new Mock();
                var collection = new BehaviorCollection();
                collection.AssociatedObject = associated;

                var item1 = new BehaviorMock();
                var item2 = new BehaviorMock();

                collection.Add(item1);
                collection.Add(item2);
                item1.AssociatedObject.Is(associated);
                item2.AssociatedObject.Is(associated);

                collection.Remove(item1);
                item1.AssociatedObject.IsNull();
                item2.AssociatedObject.Is(associated);

                collection.RemoveAt(0);
                item1.AssociatedObject.IsNull();
                item2.AssociatedObject.IsNull();
            });
        }
        #endregion

        #region Replace
        [TestMethod]
        public async Task CollectionChanged_Replace()
        {
            await UiTestHelper.ExecuteOnUiThread(() =>
            {
                var associated = new Mock();
                var collection = new BehaviorCollection();
                collection.AssociatedObject = associated;

                var item1 = new BehaviorMock();
                var item2 = new BehaviorMock();

                collection.Add(item1);
                item1.AssociatedObject.Is(associated);
                item2.AssociatedObject.IsNull();

                collection[0] = item2;
                item1.AssociatedObject.IsNull();
                item2.AssociatedObject.Is(associated);
            });
        }
        #endregion

        #region Move
        [TestMethod]
        public async Task CollectionChanged_Move()
        {
            await UiTestHelper.ExecuteOnUiThread(() =>
            {
                var associated = new Mock();
                var collection = new BehaviorCollection();
                collection.AssociatedObject = associated;

                var item1 = new BehaviorMock();
                var item2 = new BehaviorMock();
                var item3 = new BehaviorMock();

                collection.Add(item1);
                collection.Add(item2);
                collection.Add(item3);
                item1.AssociatedObject.Is(associated);
                item2.AssociatedObject.Is(associated);
                item3.AssociatedObject.Is(associated);

                collection.Move(0, 2);
                item1.AssociatedObject.Is(associated);
                item2.AssociatedObject.Is(associated);
                item3.AssociatedObject.Is(associated);
            });
        }
        #endregion

        #region Reset
        [TestMethod]
        public async Task CollectionChanged_Reset()
        {
            await UiTestHelper.ExecuteOnUiThread(() =>
            {
                var associated = new Mock();
                var collection = new BehaviorCollection();
                collection.AssociatedObject = associated;

                var item1 = new BehaviorMock();
                var item2 = new BehaviorMock();
                var item3 = new BehaviorMock();

                collection.Add(item1);
                collection.Add(item2);
                collection.Add(item3);
                item1.AssociatedObject.Is(associated);
                item2.AssociatedObject.Is(associated);
                item3.AssociatedObject.Is(associated);

                collection.Clear();
                item1.AssociatedObject.IsNull();
                item2.AssociatedObject.IsNull();
                item3.AssociatedObject.IsNull();
            });
        }
        #endregion

        #endregion

        #region Mock

        private class Mock : DependencyObject
        {
        }

        private class BehaviorMock : Behavior<Mock>
        {
        }

        #endregion
    }
}
